package com.lh0811.forge.pserv.uacs.server.config.auth;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Lists;
import com.lh0811.forge.dependency.basic_code.BeanHelper;
import com.lh0811.forge.dependency.basic_code.ListToTreeUtil;
import com.lh0811.forge.dependency.basic_web.exception.CommonException;
import com.lh0811.forge.dependency.basic_web.response.ServerResponse;
import com.lh0811.forge.dependency.security.core.model.entity.*;
import com.lh0811.forge.pserv.uacs.api.constant.UacsContant;
import com.lh0811.forge.pserv.uacs.server.repository.dao.*;
import com.lh0811.forge.pserv.uacs.server.repository.entity.*;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Component
public class VerificationHandler {

    @Resource
    private UacsPlateTenantInfoDao uacsPlateTenantInfoDao;

    @Resource
    private UacsTenantPlateUserPostRefDao uacsTenantPlateUserPostRefDao;

    @Resource
    private UacsTenantDepartmentPostDao uacsTenantDepartmentPostDao;

    @Resource
    private UacsTenantPostRoleRefDao uacsTenantPostRoleRefDao;

    @Resource
    private UacsDataRuleDao uacsDataRuleDao;

    @Resource
    private UacsTenantPostDataRuleRefDao uacsTenantPostDataRuleRefDao;

    @Resource
    private UacsPlateRoleDao uacsPlateRoleDao;

    @Resource
    private UacsPlateRoleResRefDao uacsPlateRoleResRefDao;

    @Resource
    private UacsPlateResDao uacsPlateResDao;

    @Resource
    private UacsPlateUserWechatInfoDao uacsPlateUserWechatInfoDao;

    @Resource
    private UacsPlateUserDao uacsPlateUserDao;

    // 通过平台用户信息生成 SecurityAuthority
    public SecurityAuthority genSecurityAuthority(UacsPlateUser uacsPlateUser) throws Exception {
        // 获取平台用户租户信息
        List<UacsTenantPlateUserPostRef> userPostRefList = uacsTenantPlateUserPostRefDao.lambdaQuery().eq(UacsTenantPlateUserPostRef::getPlateUserId, uacsPlateUser.getId()).list();
        if (CollectionUtils.isEmpty(userPostRefList)) {
            throw CommonException.create(ServerResponse.createByError("用户未设置岗位信息,请联系系统管理员"));
        }

        // 获取岗位关联的角色
        List<Long> postIdList = userPostRefList.stream().map(ele -> ele.getPostId()).collect(Collectors.toList());
        List<UacsTenantPostRoleRef> uacsTenantPostRoleRefList = uacsTenantPostRoleRefDao.lambdaQuery().in(UacsTenantPostRoleRef::getPostId, postIdList).list();
        if (CollectionUtils.isEmpty(uacsTenantPostRoleRefList)) {
            throw CommonException.create(ServerResponse.createByError("用户岗位未设置角色信息,请联系系统管理员"));
        }

        return getUserDefTenantSecurityAuthority(uacsPlateUser, userPostRefList);
    }

    private SecurityAuthority getUserDefTenantSecurityAuthority(UacsPlateUser uacsPlateUser, List<UacsTenantPlateUserPostRef> userPostRefList) throws Exception {
        List<SecurityRes> resList = Lists.newArrayList();
        List<SecurityMenu> menuList = Lists.newArrayList();

        // 获取用户默认的租户信息
        if (ObjectUtils.isEmpty(uacsPlateUser.getDefaultTenantId())) {
            // 设置默认租户
            Set<Long> tenantSet = userPostRefList.stream().map(ele -> ele.getTenantId()).collect(Collectors.toSet());
            Long defaultTenantId = tenantSet.stream().findAny().orElse(null);
            uacsPlateUser.setDefaultTenantId(defaultTenantId);
            // 更新用户默认租户id
            uacsPlateUserDao.lambdaUpdate()
                    .set(UacsPlateUser::getDefaultTenantId, defaultTenantId)
                    .set(UacsPlateUser::getUpdateTime, new Date())
                    .eq(UacsPlateUser::getId, uacsPlateUser.getId())
                    .update();
        }

        UacsPlateTenantInfo tenantInfo = uacsPlateTenantInfoDao.getById(uacsPlateUser.getDefaultTenantId());
        if (ObjectUtils.isEmpty(tenantInfo)) {
            throw CommonException.create(ServerResponse.createByError("租户信息不存在:" + uacsPlateUser.getDefaultTenantId()));
        }

        SecurityTenant securityTenant = new SecurityTenant();
        securityTenant.setId(tenantInfo.getId());
        securityTenant.setTenantNo(tenantInfo.getTenantNo());
        securityTenant.setTenantName(tenantInfo.getTenantName());
        securityTenant.setPostList(Lists.newArrayList());

        // 获取用户在当前租户下的岗位信息
        List<UacsTenantPlateUserPostRef> currTenantPostList = userPostRefList.stream().filter(ele -> ele.getTenantId().equals(uacsPlateUser.getDefaultTenantId())).collect(Collectors.toList());
        for (UacsTenantPlateUserPostRef uacsTenantPlateUserPostRef : currTenantPostList) {
            UacsTenantDepartmentPost departmentPost = uacsTenantDepartmentPostDao.getById(uacsTenantPlateUserPostRef.getPostId());
            if (ObjectUtils.isEmpty(departmentPost)) {
                throw CommonException.create(ServerResponse.createByError("岗位信息不存在:" + uacsTenantPlateUserPostRef.getPostId()));
            }
            SecurityPost securityPost = new SecurityPost();
            securityPost.setPostId(departmentPost.getId());
            securityPost.setPostNo(departmentPost.getPostNo());
            securityPost.setName(departmentPost.getPostName());
            securityPost.setRoleList(Lists.newArrayList());
            securityPost.setDataScopeList(Lists.newArrayList());
            // 岗位关联的角色
            List<UacsTenantPostRoleRef> postRoleRefList = uacsTenantPostRoleRefDao.lambdaQuery().eq(UacsTenantPostRoleRef::getPostId, departmentPost.getId()).list();
            if (!CollectionUtils.isEmpty(postRoleRefList)) {
                List<UacsPlateRole> appRoleList = uacsPlateRoleDao.listByIds(postRoleRefList.stream().map(ele -> ele.getRoleId()).collect(Collectors.toList()));
                if (!CollectionUtils.isEmpty(appRoleList)) {
                    for (UacsPlateRole uacsTenantAppInstRole : appRoleList) {
                        SecurityRole securityRole = new SecurityRole();
                        securityRole.setRoleId(uacsTenantAppInstRole.getId());
                        securityRole.setRoleNo(uacsTenantAppInstRole.getRoleNo());
                        securityRole.setName(uacsTenantAppInstRole.getRoleName());
                        securityRole.setResList(Lists.newArrayList());
                        // 查询角色关联的资源列表
                        List<UacsPlateRoleResRef> roleResRefList = uacsPlateRoleResRefDao.lambdaQuery().eq(UacsPlateRoleResRef::getRoleId, uacsTenantAppInstRole.getId()).list();
                        if (!CollectionUtils.isEmpty(roleResRefList)) {
                            List<UacsPlateRes> uacsPlateRes = uacsPlateResDao.listByIds(roleResRefList.stream().map(ele -> ele.getResId()).collect(Collectors.toList()));
                            if (!CollectionUtils.isEmpty(uacsPlateRes)) {
                                for (UacsPlateRes uacsPlateAppRe : uacsPlateRes) {
                                    if (!StringUtils.equals(uacsPlateAppRe.getResType(), UacsContant.ResType.菜单.getCode())) {
                                        SecurityRes securityRes = new SecurityRes();
                                        securityRes.setCode(uacsPlateAppRe.getCode());
                                        securityRes.setUrl(uacsPlateAppRe.getUrl());
                                        securityRes.setName(uacsPlateAppRe.getResName());
                                        securityRole.getResList().add(securityRes);
                                        resList.add(securityRes);
                                    } else {
                                        SecurityMenu securityMenu = new SecurityMenu();
                                        securityMenu.setId(uacsPlateAppRe.getId()); // 主键
                                        securityMenu.setPid(uacsPlateAppRe.getPid()); // 父节点id
                                        securityMenu.setResName(uacsPlateAppRe.getResName()); // 资源名称
                                        securityMenu.setUrl(uacsPlateAppRe.getUrl()); // 请求地址
                                        securityMenu.setIcon(uacsPlateAppRe.getIcon()); // 图标
                                        securityMenu.setOrderNo(uacsPlateAppRe.getOrderNo()); // 排序
                                        securityMenu.setLeafFlag(uacsPlateAppRe.getLeafFlag()); // 是否是叶子节点
                                        securityMenu.setRouter(uacsPlateAppRe.getRouter()); // 路由
                                        securityMenu.setMeta(uacsPlateAppRe.getMeta()); // 元数据
                                        menuList.add(securityMenu);
                                    }
                                }
                            }
                        }
                        securityPost.getRoleList().add(securityRole);
                    }
                }
            }

            // 岗位关联的数据权限
            List<UacsTenantPostDataRuleRef> postDataRuleRefList = uacsTenantPostDataRuleRefDao.lambdaQuery().eq(UacsTenantPostDataRuleRef::getPostId, departmentPost.getId()).list();
            if (CollectionUtils.isNotEmpty(postDataRuleRefList)) {
                List<UacsDataRule> uacsDataRuleList = uacsDataRuleDao.listByIds(postDataRuleRefList.stream().map(ele -> ele.getDataRuleId()).collect(Collectors.toList()));
                if (!CollectionUtils.isEmpty(uacsDataRuleList)) {
                    List<SecurityDataRule> dataRuleVoList = BeanHelper.copyList(uacsDataRuleList, SecurityDataRule.class);
                    if (!CollectionUtils.isEmpty(dataRuleVoList)) {
                        securityPost.setDataScopeList(dataRuleVoList);
                    }
                }
            }

            // 添加岗位信息
            securityTenant.getPostList().add(securityPost);
        }

        // menuList -> menuTree
        if (resList.stream().filter(ele -> StringUtils.equals(ele.getUrl(), "/**")).count() > 0) {
            List<UacsPlateRes> list = uacsPlateResDao.lambdaQuery()
                    .in(UacsPlateRes::getResType, UacsContant.ResType.菜单.getCode())
                    .orderByAsc(UacsPlateRes::getOrderNo)
                    .list();
            menuList = list.stream().map(ele -> {
                SecurityMenu securityMenu = new SecurityMenu();
                securityMenu.setId(ele.getId()); // 主键
                securityMenu.setPid(ele.getPid()); // 父节点id
                securityMenu.setResName(ele.getResName()); // 资源名称
                securityMenu.setUrl(ele.getUrl()); // 请求地址
                securityMenu.setIcon(ele.getIcon()); // 图标
                securityMenu.setOrderNo(ele.getOrderNo()); // 排序
                securityMenu.setLeafFlag(ele.getLeafFlag()); // 是否是叶子节点
                securityMenu.setRouter(ele.getRouter()); // 路由
                securityMenu.setMeta(ele.getMeta()); // 元数据
                return securityMenu;
            }).collect(Collectors.toList());
        }
        JSONArray menuTreeObj = ListToTreeUtil.listToTree(menuList, "0", "pid", "id", "children");

        // 获取用户的微信信息
        UacsPlateUserWechatInfo uacsPlateUserWechatInfo = uacsPlateUserWechatInfoDao.lambdaQuery()
                .eq(UacsPlateUserWechatInfo::getUserId, uacsPlateUser.getId())
                .one();
        WechatUserInfo wechatUserInfo = BeanHelper.copyBean(uacsPlateUserWechatInfo, WechatUserInfo.class);
        JSONObject extInfo = new JSONObject();
        extInfo.put("wechatUserInfo", wechatUserInfo);


        // 补充用户租户列表
        List<SecurityTenant> tenantList = Lists.newArrayList();
        List<UacsPlateTenantInfo> tenantInfoList = uacsPlateTenantInfoDao.lambdaQuery().in(UacsPlateTenantInfo::getId, userPostRefList.stream().map(ele -> ele.getTenantId()).collect(Collectors.toList())).list();
        tenantList.addAll(tenantInfoList.stream().map(ele -> new SecurityTenant(ele.getId(), ele.getTenantNo(), ele.getTenantName(), Lists.newArrayList())).collect(Collectors.toList()));

        SecurityUser securityUser = new SecurityUser(String.valueOf(uacsPlateUser.getId()), uacsPlateUser.getPlateUserNo(), uacsPlateUser.getPhone(), uacsPlateUser.getRealName(), securityTenant, tenantList, menuList, menuTreeObj.toJavaList(SecurityMenu.class), resList, extInfo);
        return new SecurityAuthority(securityUser);
    }


    public SecurityAuthority getUserTenantSecurityAuthority(UacsPlateUser uacsPlateUser, Long tenantId) throws Exception {
        List<SecurityRes> resList = Lists.newArrayList();
        List<SecurityMenu> menuList = Lists.newArrayList();

        // 获取平台用户租户信息
        List<UacsTenantPlateUserPostRef> userPostRefList = uacsTenantPlateUserPostRefDao.lambdaQuery().eq(UacsTenantPlateUserPostRef::getPlateUserId, uacsPlateUser.getId()).list();
        if (CollectionUtils.isEmpty(userPostRefList)) {
            throw CommonException.create(ServerResponse.createByError("用户未设置岗位信息,请联系系统管理员"));
        }
        Set<Long> tenantIdList = userPostRefList.stream().map(ele -> ele.getTenantId()).collect(Collectors.toSet());
        if (!tenantIdList.contains(tenantId)) {
            throw CommonException.create(ServerResponse.createByError("当前用户在切换租户下无岗位配置"));
        }

        // 设置默认租户
        uacsPlateUser.setDefaultTenantId(tenantId);
        // 更新用户默认租户id
        uacsPlateUserDao.lambdaUpdate()
                .set(UacsPlateUser::getDefaultTenantId, tenantId)
                .set(UacsPlateUser::getUpdateTime, new Date())
                .eq(UacsPlateUser::getId, uacsPlateUser.getId())
                .update();

        UacsPlateTenantInfo tenantInfo = uacsPlateTenantInfoDao.getById(uacsPlateUser.getDefaultTenantId());
        if (ObjectUtils.isEmpty(tenantInfo)) {
            throw CommonException.create(ServerResponse.createByError("租户信息不存在:" + uacsPlateUser.getDefaultTenantId()));
        }

        SecurityTenant securityTenant = new SecurityTenant();
        securityTenant.setId(tenantInfo.getId());
        securityTenant.setTenantNo(tenantInfo.getTenantNo());
        securityTenant.setTenantName(tenantInfo.getTenantName());
        securityTenant.setPostList(Lists.newArrayList());

        // 获取用户在当前租户下的岗位信息
        List<UacsTenantPlateUserPostRef> currTenantPostList = userPostRefList.stream().filter(ele -> ele.getTenantId().equals(uacsPlateUser.getDefaultTenantId())).collect(Collectors.toList());
        for (UacsTenantPlateUserPostRef uacsTenantPlateUserPostRef : currTenantPostList) {
            UacsTenantDepartmentPost departmentPost = uacsTenantDepartmentPostDao.getById(uacsTenantPlateUserPostRef.getPostId());
            if (ObjectUtils.isEmpty(departmentPost)) {
                throw CommonException.create(ServerResponse.createByError("岗位信息不存在:" + uacsTenantPlateUserPostRef.getPostId()));
            }
            SecurityPost securityPost = new SecurityPost();
            securityPost.setPostId(departmentPost.getId());
            securityPost.setPostNo(departmentPost.getPostNo());
            securityPost.setName(departmentPost.getPostName());
            securityPost.setRoleList(Lists.newArrayList());
            securityPost.setDataScopeList(Lists.newArrayList());
            // 岗位关联的角色
            List<UacsTenantPostRoleRef> postRoleRefList = uacsTenantPostRoleRefDao.lambdaQuery().eq(UacsTenantPostRoleRef::getPostId, departmentPost.getId()).list();
            if (!CollectionUtils.isEmpty(postRoleRefList)) {
                List<UacsPlateRole> appRoleList = uacsPlateRoleDao.listByIds(postRoleRefList.stream().map(ele -> ele.getRoleId()).collect(Collectors.toList()));
                if (!CollectionUtils.isEmpty(appRoleList)) {
                    for (UacsPlateRole uacsTenantAppInstRole : appRoleList) {
                        SecurityRole securityRole = new SecurityRole();
                        securityRole.setRoleId(uacsTenantAppInstRole.getId());
                        securityRole.setRoleNo(uacsTenantAppInstRole.getRoleNo());
                        securityRole.setName(uacsTenantAppInstRole.getRoleName());
                        securityRole.setResList(Lists.newArrayList());
                        // 查询角色关联的资源列表
                        List<UacsPlateRoleResRef> roleResRefList = uacsPlateRoleResRefDao.lambdaQuery().eq(UacsPlateRoleResRef::getRoleId, uacsTenantAppInstRole.getId()).list();
                        if (!CollectionUtils.isEmpty(roleResRefList)) {
                            List<UacsPlateRes> uacsPlateRes = uacsPlateResDao.listByIds(roleResRefList.stream().map(ele -> ele.getResId()).collect(Collectors.toList()));
                            if (!CollectionUtils.isEmpty(uacsPlateRes)) {
                                for (UacsPlateRes uacsPlateAppRe : uacsPlateRes) {
                                    if (!StringUtils.equals(uacsPlateAppRe.getResType(), UacsContant.ResType.菜单.getCode())) {
                                        SecurityRes securityRes = new SecurityRes();
                                        securityRes.setCode(uacsPlateAppRe.getCode());
                                        securityRes.setUrl(uacsPlateAppRe.getUrl());
                                        securityRes.setName(uacsPlateAppRe.getResName());
                                        securityRole.getResList().add(securityRes);
                                        resList.add(securityRes);
                                    } else {
                                        SecurityMenu securityMenu = new SecurityMenu();
                                        securityMenu.setId(uacsPlateAppRe.getId()); // 主键
                                        securityMenu.setPid(uacsPlateAppRe.getPid()); // 父节点id
                                        securityMenu.setResName(uacsPlateAppRe.getResName()); // 资源名称
                                        securityMenu.setUrl(uacsPlateAppRe.getUrl()); // 请求地址
                                        securityMenu.setIcon(uacsPlateAppRe.getIcon()); // 图标
                                        securityMenu.setOrderNo(uacsPlateAppRe.getOrderNo()); // 排序
                                        securityMenu.setLeafFlag(uacsPlateAppRe.getLeafFlag()); // 是否是叶子节点
                                        securityMenu.setRouter(uacsPlateAppRe.getRouter()); // 路由
                                        securityMenu.setMeta(uacsPlateAppRe.getMeta()); // 元数据
                                        menuList.add(securityMenu);
                                    }
                                }
                            }
                        }
                        securityPost.getRoleList().add(securityRole);
                    }
                }
            }

            // 岗位关联的数据权限
            List<UacsTenantPostDataRuleRef> postDataRuleRefList = uacsTenantPostDataRuleRefDao.lambdaQuery().eq(UacsTenantPostDataRuleRef::getPostId, departmentPost.getId()).list();
            if (CollectionUtils.isNotEmpty(postDataRuleRefList)) {
                List<UacsDataRule> uacsDataRuleList = uacsDataRuleDao.listByIds(postDataRuleRefList.stream().map(ele -> ele.getDataRuleId()).collect(Collectors.toList()));
                if (!CollectionUtils.isEmpty(uacsDataRuleList)) {
                    List<SecurityDataRule> dataRuleVoList = BeanHelper.copyList(uacsDataRuleList, SecurityDataRule.class);
                    if (!CollectionUtils.isEmpty(dataRuleVoList)) {
                        securityPost.setDataScopeList(dataRuleVoList);
                    }
                }
            }

            // 添加岗位信息
            securityTenant.getPostList().add(securityPost);
        }

        // menuList -> menuTree
        if (resList.stream().filter(ele -> StringUtils.equals(ele.getUrl(), "/**")).count() > 0) {
            List<UacsPlateRes> list = uacsPlateResDao.lambdaQuery()
                    .in(UacsPlateRes::getResType, UacsContant.ResType.菜单.getCode())
                    .orderByAsc(UacsPlateRes::getOrderNo)
                    .list();
            menuList = list.stream().map(ele -> {
                SecurityMenu securityMenu = new SecurityMenu();
                securityMenu.setId(ele.getId()); // 主键
                securityMenu.setPid(ele.getPid()); // 父节点id
                securityMenu.setResName(ele.getResName()); // 资源名称
                securityMenu.setUrl(ele.getUrl()); // 请求地址
                securityMenu.setIcon(ele.getIcon()); // 图标
                securityMenu.setOrderNo(ele.getOrderNo()); // 排序
                securityMenu.setLeafFlag(ele.getLeafFlag()); // 是否是叶子节点
                securityMenu.setRouter(ele.getRouter()); // 路由
                securityMenu.setMeta(ele.getMeta()); // 元数据
                return securityMenu;
            }).collect(Collectors.toList());
        }
        JSONArray menuTreeObj = ListToTreeUtil.listToTree(menuList, "0", "pid", "id", "children");

        // 获取用户的微信信息
        UacsPlateUserWechatInfo uacsPlateUserWechatInfo = uacsPlateUserWechatInfoDao.lambdaQuery()
                .eq(UacsPlateUserWechatInfo::getUserId, uacsPlateUser.getId())
                .one();
        WechatUserInfo wechatUserInfo = BeanHelper.copyBean(uacsPlateUserWechatInfo, WechatUserInfo.class);
        JSONObject extInfo = new JSONObject();
        extInfo.put("wechatUserInfo", wechatUserInfo);

        // 补充用户租户列表
        List<SecurityTenant> tenantList = Lists.newArrayList();
        List<UacsPlateTenantInfo> tenantInfoList = uacsPlateTenantInfoDao.lambdaQuery().in(UacsPlateTenantInfo::getId, userPostRefList.stream().map(ele -> ele.getTenantId()).collect(Collectors.toList())).list();
        tenantList.addAll(tenantInfoList.stream().map(ele -> new SecurityTenant(ele.getId(), ele.getTenantNo(), ele.getTenantName(), Lists.newArrayList())).collect(Collectors.toList()));

        SecurityUser securityUser = new SecurityUser(String.valueOf(uacsPlateUser.getId()), uacsPlateUser.getPlateUserNo(), uacsPlateUser.getPhone(), uacsPlateUser.getRealName(), securityTenant, tenantList, menuList, menuTreeObj.toJavaList(SecurityMenu.class), resList, extInfo);
        return new SecurityAuthority(securityUser);
    }
}
